#include "evm_module.h"


evm_val_t tcp_msg_hander(evm_t * e,void *msg) {
    tcp_callback_t *msgbuff = (tcp_callback_t *)msg;

    evm_val_t *args = evm_list_create(e, GC_LIST, 1);
    if(strcmp(msgbuff->type, "data") == 0){
        if(msgbuff->buffer!=NULL && msgbuff->buffer->data!=NULL){
            int len = msgbuff->buffer->len;
            evm_val_t *buffer = evm_buffer_create(e, len);
            if(buffer != NULL){
                char *addr = (char *)evm_buffer_addr(buffer);
                memcpy(addr, msgbuff->buffer->data, len);
            }
            evm_list_set(e, args, 0, *buffer);
        }
    }else if(strcmp(msgbuff->type, "end") == 0){
        return EVM_VAL_UNDEFINED;
    }

    return *args;
}

void tcp_msg_free(void *msg){
    if(msg == NULL)
        return;
    tcp_callback_t *msgbuff = (tcp_callback_t *)msg;
    if(msgbuff->buffer !=NULL){
        if(msgbuff->buffer->data != NULL){
            evm_free(msgbuff->buffer->data);
        }
        evm_free(msgbuff->buffer);
        msgbuff->buffer = NULL;
    }
    evm_free(msgbuff);
    msg = NULL;
}

static evm_val_t evm_module_tcp_on(evm_t *e, evm_val_t *p, int argc, evm_val_t *v)
{
    if(argc!=3)
        return EVM_VAL_UNDEFINED;

    if(!evm_is_number(v) || !evm_is_number(v+1) || !evm_2_string(v+2))
        return EVM_VAL_UNDEFINED;

    int id = evm_2_integer(v);
    int instance = evm_2_integer(v+1);
    char *event = (char *)evm_2_string(v+2);

    evm_event_msg_t *msg = evm_module_msg_create();

    int str_len = strlen(event);
    msg->event = evm_malloc(str_len + 1);
    memcpy(msg->event, event,str_len);
    msg->event[str_len] = 0;

    msg->id = instance;

    msg->cb = tcp_msg_hander;
    msg->free = tcp_msg_free;

    evm_tcp_t *tcp = evm_module_tcp_getInstance();
    if(tcp == NULL)
        return EVM_VAL_UNDEFINED;

    tcp->on(id, msg);
    return EVM_VAL_UNDEFINED;
}

evm_err_t evm_module_tcp(evm_t *e) {
    if(evm_module_tcp_init() != 0)
        return ec_memory;

    evm_tcp_t *tcp = evm_module_tcp_getInstance();
    if(tcp == NULL)
        return ec_err;

    evm_cffi_t funcs[] = {
        {"connect", (uintptr_t)tcp->connect, "ipii"},
        {"send", (uintptr_t)tcp->send, "iipi"},
        {"close", (uintptr_t)tcp->close, "ii"},
        {NULL, 0, NULL}
    };

    evm_builtin_t builtin[] = {
        {"on", evm_mk_native((intptr_t)evm_module_tcp_on)},
        {NULL, EVM_VAL_UNDEFINED}
    };
    evm_module_effi_create(e, "@native.tcp", funcs , builtin);
    return e->err;
}

